package crmdna.common;

import java.util.ArrayList;
import java.util.List;

import com.google.appengine.api.datastore.AsyncDatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.PropertyProjection;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.googlecode.objectify.Key;

public class DSUtils {
  @SuppressWarnings("unchecked")
  public static <T1, T2> List<T2> executeProjectionQuery(String kind, Iterable<Key<T1>> keys,
      String property, Class<T2> type) {

    List<com.google.appengine.api.datastore.Key> rawKeys = new ArrayList<>();
    for (Key<?> key : keys) {
      rawKeys.add(key.getRaw());
    }

    AsyncDatastoreService datastore = DatastoreServiceFactory.getAsyncDatastoreService();

    com.google.appengine.api.datastore.Query.Filter filter =
        new com.google.appengine.api.datastore.Query.FilterPredicate(Entity.KEY_RESERVED_PROPERTY,
            FilterOperator.IN, rawKeys);

    com.google.appengine.api.datastore.Query q = new com.google.appengine.api.datastore.Query(kind);

    q.setFilter(filter).addProjection(new PropertyProjection(property, type));

    List<Entity> entities = datastore.prepare(q).asList(FetchOptions.Builder.withLimit(20000));

    List<T2> list = new ArrayList<>();
    for (Entity entity : entities) {
      list.add((T2) entity.getProperty(property));
    }

    return list;
  }

  @SuppressWarnings("unchecked")
  public static <T1, T2, T3> List<T2> executeProjectionQuery2(Class<T3> kind,
      Iterable<Key<T1>> keys, String property, Class<T2> type) {

    // do not use this. use objectify projectection queries

    List<com.google.appengine.api.datastore.Key> rawKeys = new ArrayList<>();
    for (Key<?> key : keys) {
      rawKeys.add(key.getRaw());
    }

    AsyncDatastoreService datastore = DatastoreServiceFactory.getAsyncDatastoreService();

    com.google.appengine.api.datastore.Query.Filter filter =
        new com.google.appengine.api.datastore.Query.FilterPredicate(Entity.KEY_RESERVED_PROPERTY,
            FilterOperator.IN, rawKeys);

    com.google.appengine.api.datastore.Query q =
        new com.google.appengine.api.datastore.Query(kind.getSimpleName());

    q.setFilter(filter).addProjection(new PropertyProjection(property, type));

    List<Entity> entities = datastore.prepare(q).asList(FetchOptions.Builder.withLimit(100000));

    List<T2> list = new ArrayList<>();
    for (Entity entity : entities) {
      list.add((T2) entity.getProperty(property));
    }

    return list;
  }

}
